home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / math / ast51src.zip / XSCREEN.C < prev   
C/C++ Source or Header  |  1995-12-31  |  52KB  |  1,772 lines

  1. /*
  2. ** Astrolog (Version 5.10) File: xscreen.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (Astara@msn.com). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 12/27/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38.  
  39.  
  40. #ifdef GRAPH
  41. /*
  42. ******************************************************************************
  43. ** Astrolog Icon.
  44. ******************************************************************************
  45. */
  46.  
  47. #ifdef X11
  48. /* This information used to define Astrolog's X icon (Rainbow over Third */
  49. /* Eye) is identical to the output format used by the bitmap program.    */
  50. /* You could extract this section and run xsetroot -bitmap on it.        */
  51.  
  52. #define icon_width 63
  53. #define icon_height 32
  54. static char icon_bits[] = {
  55.  0x00,0x00,0x00,0xa8,0x0a,0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x55,0x01,0x00,
  56.  0x00,0x00,0x00,0xa8,0xaa,0xaa,0x0a,0x00,0x00,0x00,0x00,0x54,0xf5,0x57,0x15,
  57.  0x00,0x00,0x00,0x80,0xaa,0xaa,0xaa,0xaa,0x00,0x00,0x00,0x40,0xd5,0xff,0xff,
  58.  0x55,0x01,0x00,0x00,0xa0,0xaa,0xaa,0xaa,0xaa,0x02,0x00,0x00,0x50,0xfd,0xff,
  59.  0xff,0x5f,0x05,0x00,0x00,0xa8,0xaa,0x2a,0xaa,0xaa,0x0a,0x00,0x00,0xd4,0xff,
  60.  0xaf,0xfa,0xff,0x15,0x00,0x00,0xaa,0x2a,0x00,0x00,0xaa,0x2a,0x00,0x00,0xf5,
  61.  0xbf,0xaa,0xaa,0xfe,0x57,0x00,0x80,0xaa,0x02,0x00,0x00,0xa0,0xaa,0x00,0x40,
  62.  0xfd,0xab,0xfa,0xaf,0xea,0x5f,0x01,0xa0,0xaa,0x80,0xff,0xff,0x80,0xaa,0x02,
  63.  0x50,0xff,0xea,0xff,0xff,0xab,0x7f,0x05,0xa0,0x2a,0xf0,0xff,0xff,0x07,0xaa,
  64.  0x02,0xd0,0xbf,0xfa,0x0f,0xf8,0xaf,0x7e,0x05,0xa8,0x0a,0xfc,0x01,0xc0,0x1f,
  65.  0xa8,0x0a,0xd4,0xaf,0x7e,0x00,0x00,0xbf,0xfa,0x15,0xa8,0x0a,0x3f,0x00,0x00,
  66.  0x7e,0xa8,0x0a,0xf4,0xaf,0x1f,0xe0,0x03,0xfc,0xfa,0x15,0xaa,0x82,0x0f,0xdc,
  67.  0x1d,0xf8,0xa0,0x2a,0xf4,0xab,0x07,0x23,0x62,0xf0,0xea,0x17,0xaa,0xc2,0x87,
  68.  0x91,0xc4,0xf0,0xa1,0x2a,0xf4,0xeb,0xc3,0xd0,0x85,0xe1,0xeb,0x17,0xaa,0xe0,
  69.  0x83,0x91,0xc4,0xe0,0x83,0x2a,0xf5,0xeb,0x03,0x23,0x62,0xe0,0xeb,0x57,0xaa,
  70.  0xe0,0x01,0xdc,0x1d,0xc0,0x83,0x2a,0xf5,0xeb,0x01,0xe0,0x03,0xc0,0xeb,0x57,
  71.  0xaa,0xe0,0x01,0x00,0x00,0xc0,0x83,0x2a,0xfd,0xeb,0x01,0x00,0x00,0xc0,0xeb,
  72.  0x5f};
  73. #endif
  74.  
  75.  
  76. /*
  77. ******************************************************************************
  78. ** Interactive Screen Graphics Routines.
  79. ******************************************************************************
  80. */
  81.  
  82. /* Set up all the colors used by the program, i.e. the foreground and   */
  83. /* background colors, and all the colors in the object arrays, based on */
  84. /* whether or not we are in monochrome and/or reverse video mode.       */
  85.  
  86. void InitColorsX()
  87. {
  88.   int i;
  89. #ifdef X11
  90.   Colormap cmap;
  91.   XColor xcol;
  92.  
  93.   if (!gi.fFile) {
  94.     cmap = XDefaultColormap(gi.disp, gi.screen);
  95.  
  96.     /* Allocate a color from the present X11 colormap. Given a string like */
  97.     /* "violet", allocate this color and return a value specifying it.     */
  98.  
  99.     for (i = 0; i < 16; i++) {
  100.       XParseColor(gi.disp, cmap, szColorX[i], &xcol);
  101.       XAllocColor(gi.disp, cmap, &xcol);
  102.       rgbind[i] = xcol.pixel;
  103.     }
  104.   }
  105. #endif
  106.   gi.kiOn   = kMainA[!gs.fInverse];
  107.   gi.kiOff  = kMainA[gs.fInverse];
  108.   gi.kiLite = gs.fColor ? kMainA[2+gs.fInverse] : gi.kiOn;
  109.   gi.kiGray = gs.fColor ? kMainA[3-gs.fInverse] : gi.kiOn;
  110.   for (i = 0; i <= 8; i++)
  111.     kMainB[i]    = gs.fColor ? kMainA[i]    : gi.kiOn;
  112.   for (i = 0; i <= 7; i++)
  113.     kRainbowB[i] = gs.fColor ? kRainbowA[i] : gi.kiOn;
  114.   for (i = 0; i < 4; i++)
  115.     kElemB[i]    = gs.fColor ? kElemA[i]    : gi.kiOn;
  116.   for (i = 0; i <= cAspect; i++)
  117.     kAspB[i]     = gs.fColor ? kAspA[i]     : gi.kiOn;
  118.   for (i = 0; i <= cObj; i++)
  119.     kObjB[i]     = gs.fColor ? kObjA[i]     : gi.kiOn;
  120. #ifdef X11
  121.   if (!gi.fFile) {
  122.     XSetBackground(gi.disp, gi.gc,   rgbind[gi.kiOff]);
  123.     XSetForeground(gi.disp, gi.pmgc, rgbind[gi.kiOff]);
  124.   }
  125. #endif
  126. }
  127.  
  128.  
  129. #ifdef ISG
  130. /* This routine opens up and initializes a window and prepares it to be */
  131. /* drawn upon, and gets various information about the display, too.     */
  132.  
  133. void BeginX()
  134. {
  135. #ifdef X11
  136.   gi.disp = XOpenDisplay(gs.szDisplay);
  137.   if (gi.disp == NULL) {
  138.     PrintError("Can't open display.");
  139.     Terminate(tcFatal);
  140.   }
  141.   gi.screen = DefaultScreen(gi.disp);
  142.   bg = BlackPixel(gi.disp, gi.screen);
  143.   fg = WhitePixel(gi.disp, gi.screen);
  144.   hint.x = gi.xOffset; hint.y = gi.yOffset;
  145.   hint.width = gs.xWin; hint.height = gs.yWin;
  146.   hint.min_width = BITMAPX1; hint.min_height = BITMAPY1;
  147.   hint.max_width = BITMAPX;  hint.max_height = BITMAPY;
  148.   hint.flags = PPosition | PSize | PMaxSize | PMinSize;
  149. #if FALSE
  150.   wmhint = XGetWMHints(gi.disp, gi.wind);
  151.   wmhint->input = True;
  152.   XSetWMHints(gi.disp, gi.wind, wmhint);
  153. #endif
  154.   gi.depth = DefaultDepth(gi.disp, gi.screen);
  155.   if (gi.depth < 5) {
  156.     gi.fMono = fTrue;      /* Is this a monochrome monitor? */
  157.     gs.fColor = fFalse;
  158.   }
  159.   gi.root = RootWindow(gi.disp, gi.screen);
  160.   if (gs.fRoot)
  161.     gi.wind = gi.root;     /* If -XB in effect, we'll use the root window. */
  162.   else
  163.     gi.wind = XCreateSimpleWindow(gi.disp, DefaultRootWindow(gi.disp),
  164.       hint.x, hint.y, hint.width, hint.height, 5, fg, bg);
  165.   gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  166.   gi.icon = XCreateBitmapFromData(gi.disp, DefaultRootWindow(gi.disp),
  167.     icon_bits, icon_width, icon_height);
  168.   if (!gs.fRoot)
  169.     XSetStandardProperties(gi.disp, gi.wind, szAppName, szAppName, gi.icon,
  170.       (char **)xkey, 0, &hint);
  171.  
  172.   /* We have two graphics workareas. One is what the user currently sees in */
  173.   /* the window, and the other is what we are currently drawing on. When    */
  174.   /* done, we can quickly copy this to the viewport for a smooth look.      */
  175.  
  176.   gi.gc = XCreateGC(gi.disp, gi.wind, 0, 0);
  177.   XSetGraphicsExposures(gi.disp, gi.gc, 0);
  178.   gi.pmgc = XCreateGC(gi.disp, gi.wind, 0, 0);
  179.   InitColorsX();                                  /* Go set up colors. */
  180.   if (!gs.fRoot)
  181.     XSelectInput(gi.disp, gi.wind, KeyPressMask | StructureNotifyMask |
  182.       ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
  183.   XMapRaised(gi.disp, gi.wind);
  184.   XSync(gi.disp, 0);
  185.   XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  186. #endif /* X11 */
  187.  
  188. #ifdef WIN
  189.   if (wi.fChartWindow && (wi.xClient != gs.xWin ||
  190.     wi.yClient != gs.yWin) && wi.hdcPrint == hdcNil)
  191.     ResizeWindowToChart();
  192.   gi.xOffset = MulDiv(wi.xClient - gs.xWin, wi.xScroll, nScrollDiv);
  193.   gi.yOffset = MulDiv(wi.yClient - gs.yWin, wi.yScroll, nScrollDiv);
  194.   SetWindowOrg(wi.hdc, -gi.xOffset, -gi.yOffset);
  195.   SetWindowExt(wi.hdc, wi.xClient, wi.yClient);
  196.   SetMapMode(wi.hdc, MM_ANISOTROPIC);
  197.   SelectObject(wi.hdc, GetStockObject(NULL_PEN));
  198.   SelectObject(wi.hdc, GetStockObject(NULL_BRUSH));
  199.   if (!gs.fJetTrail || wi.hdcPrint != hdcNil)
  200.     PatBlt(wi.hdc, -gi.xOffset, -gi.yOffset, wi.xClient, wi.yClient,
  201.       gs.fInverse ? WHITENESS : BLACKNESS);
  202.   InitColorsX();
  203. #endif /* WIN */
  204.  
  205. #ifdef MSG
  206.   if (!FValidResmode(gi.nRes))    /* Initialize graphics mode to hi-res. */
  207.     gi.nRes = gs.nResHi;
  208.   _setvideomode(gi.nRes == -1 ? _VRES16COLOR : gi.nRes);
  209.   if (_grstatus()) {
  210.     PrintError("Can't enter graphics mode.");
  211.     Terminate(tcFatal);
  212.   }
  213.   _getvideoconfig((struct videoconfig far *) &gi.cfg);
  214.   if (gi.cfg.numcolors < 16) {
  215.     gi.fMono  = fTrue;
  216.     gs.fColor = fFalse;
  217.   }
  218.   _remapallpalette((long FPTR *) rgb);
  219.   _setactivepage(0);
  220.   _setvisualpage(0);
  221.   InitColorsX();
  222. #ifdef MOUSE
  223.   MouseInit(xPcScreen, yPcScreen);
  224. #endif
  225.   /* Make sure we reset textrows upon restart. */
  226.   gs.nTextRows = abs(gs.nTextRows);
  227. #endif /* MSG */
  228.  
  229. #ifdef BGI
  230.   int i;
  231.   static struct palettetype pal;
  232.  
  233.   if (!FValidResmode(gi.nRes))    /* Initialize graphics mode to hi-res. */
  234.     gi.nRes = gs.nResHi;
  235.   if (!gi.fLoaded) {
  236.     registerfarbgidriver(ATT_driver_far);      /* attf.obj     */
  237.     registerfarbgidriver(CGA_driver_far);      /* cgaf.obj     */
  238.     registerfarbgidriver(EGAVGA_driver_far);   /* egavgaf.obj  */
  239.     registerfarbgidriver(Herc_driver_far);     /* hercf.obj    */
  240.     registerfarbgidriver(IBM8514_driver_far);  /* ibm8514f.obj */
  241.     registerfarbgidriver(PC3270_driver_far);   /* pc3270f.obj  */
  242.     gi.nDriver = DETECT;
  243.     initgraph(&gi.nDriver, &gi.nGraph, "");
  244.     gi.fLoaded = fTrue;
  245.   }
  246.   if (gi.nRes <= 0) {
  247.     switch (gi.nDriver) {
  248.     case CGA:      gi.nGraph = CGAHI;      break;
  249.     case MCGA:     gi.nGraph = MCGAHI;     break;
  250.     case EGA:      gi.nGraph = EGAHI;      break;
  251.     case EGA64:    gi.nGraph = EGA64HI;    break;
  252.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  253.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  254.     case ATT400:   gi.nGraph = ATT400HI;   break;
  255.     case VGA:      gi.nGraph = VGAHI;      break;
  256.     case PC3270:   gi.nGraph = PC3270HI;   break;
  257.     case IBM8514:  gi.nGraph = IBM8514HI;  break;
  258.     default:       gi.nGraph = 0;
  259.     }
  260.   } else {
  261.     switch (gi.nDriver) {
  262.     case CGA:      gi.nGraph = CGAHI;      break;
  263.     case MCGA:     gi.nGraph = MCGAHI;     break;
  264.     case EGA:      gi.nGraph = EGAHI;      break;
  265.     case EGA64:    gi.nGraph = EGA64HI;    break;
  266.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  267.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  268.     case ATT400:   gi.nGraph = ATT400HI;   break;
  269.     case VGA:      gi.nGraph = VGAMED;     break;
  270.     case PC3270:   gi.nGraph = PC3270HI;   break;
  271.     case IBM8514:  gi.nGraph = IBM8514LO;  break;
  272.     default:       gi.nGraph = 0;
  273.     }
  274.   }
  275.   setgraphmode(gi.nGraph);
  276.   if (graphresult()) {
  277.     PrintError("Can't enter graphics mode.");
  278.     Terminate(tcFatal);
  279.   }
  280.   gi.nPages = 1 + (gi.nDriver == HERCMONO ||
  281.     (gi.nDriver == VGA && gi.nGraph != VGAHI) || gi.nDriver == EGA);
  282.   if (getmaxcolor()+1 < 16) {
  283.     gi.fMono  = fTrue;
  284.     gs.fColor = fFalse;
  285.   }
  286.   getpalette(&pal);
  287.   for (i = 0; i < pal.size; i++)
  288.     pal.colors[i] = (char)rgb[i];
  289.   setallpalette(&pal);
  290.   setactivepage(0);
  291.   setvisualpage(0);
  292.   gi.nPageCur = 0;
  293.   InitColorsX();
  294. #ifdef MOUSE
  295.   MouseInit(xPcScreen, yPcScreen);
  296. #endif
  297.   /* Make sure we reset textrows upon restart. */
  298.   gs.nTextRows = abs(gs.nTextRows);
  299. #endif /* BGI */
  300. }
  301.  
  302.  
  303. /* Add a certain amount of time to the current hour/day/month/year quantity */
  304. /* defining the present chart. This is used by the chart animation feature. */
  305. /* We can add or subtract anywhere from 1 to 9 seconds, minutes, hours,     */
  306. /* days, months, years, decades, centuries, or millenia in any one call.    */
  307. /* This is mainly just addition to the appropriate quantity, but we have    */
  308. /* to check for overflows, e.g. Dec 30 + 3 days = Jan 2 of Current year + 1 */
  309.  
  310. void AddTime(mode, toadd)
  311. int mode, toadd;
  312. {
  313.   int d;
  314.   real h, m;
  315.  
  316.   if (!FBetween(mode, 1, 9))
  317.     mode = 4;
  318.  
  319.   h = RFloor(TT);
  320.   m = RFract(TT)*100.0;
  321.   if (mode == 1)
  322.     m += 1.0/60.0*(real)toadd;    /* Add seconds. */
  323.   else if (mode == 2)
  324.     m += (real)toadd;             /* add minutes. */
  325.  
  326.   /* Add hours, either naturally or if minute value overflowed. */
  327.  
  328.   if (m < 0.0 || m >= 60.0 || mode == 3) {
  329.     if (m >= 60.0) {
  330.       m -= 60.0; toadd = NSgn(toadd);
  331.     } else if (m < 0.0) {
  332.       m += 60.0; toadd = NSgn(toadd);
  333.     }
  334.     h += (real)toadd;
  335.   }
  336.  
  337.   /* Add days, either naturally or if hour value overflowed. */
  338.  
  339.   if (h >= 24.0 || h < 0.0 || mode == 4) {
  340.     if (h >= 24.0) {
  341.       h -= 24.0; toadd = NSgn(toadd);
  342.     } else if (h < 0.0) {
  343.       h += 24.0; toadd = NSgn(toadd);
  344.     }
  345.     DD = AddDay(MM, DD, YY, toadd);
  346.   }
  347.  
  348.   /* Add months, either naturally or if day value overflowed. */
  349.  
  350.   if (DD > (d = DayInMonth(MM, YY)) || DD < 1 || mode == 5) {
  351.     if (DD > d) {
  352.       DD -= d; toadd = NSgn(toadd);
  353.     } else if (DD < 1) {
  354.       DD += DayInMonth(Mod12(MM - 1), YY);
  355.       toadd = NSgn(toadd);
  356.     }
  357.     MM += toadd;
  358.   }
  359.  
  360.   /* Add years, either naturally or if month value overflowed. */
  361.  
  362.   if (MM > 12 || MM < 1 || mode == 6) {
  363.     if (MM > 12) {
  364.       MM -= 12; toadd = NSgn(toadd);
  365.     } else if (MM < 1) {
  366.       MM += 12; toadd = NSgn(toadd);
  367.     }
  368.     YY += toadd;
  369.   }
  370.   if (mode == 7)
  371.     YY += 10 * toadd;      /* Add decades.   */
  372.   else if (mode == 8)
  373.     YY += 100 * toadd;     /* Add centuries. */
  374.   else if (mode == 9)
  375.     YY += 1000 * toadd;    /* Add millenia.  */
  376.   TT = h+m/100.0;          /* Recalibrate hour time. */
  377. }
  378.  
  379.  
  380. /* Animate the current chart based on the given values indicating how much  */
  381. /* to update by. We update and recast the current chart info appropriately. */
  382.  
  383. void Animate(mode, toadd)
  384. int mode, toadd;
  385. {
  386.   if (gi.nMode == gWorldMap || gi.nMode == gGlobe || gi.nMode == gPolar) {
  387.     gs.nRot += toadd;
  388.     if (gs.nRot >= nDegMax)     /* For animating globe display, add */
  389.       gs.nRot -= nDegMax;       /* in appropriate degree value.     */
  390.     else if (gs.nRot < 0)
  391.       gs.nRot += nDegMax;
  392.   } else {
  393.     if (mode == 10) {
  394. #ifdef TIME
  395.       /* For the continuous chart update to present moment */
  396.       /* animation mode, go get whatever time it is now.   */
  397.       FInputData(szNowCore);
  398. #else
  399.       ciCore = ciMain;
  400.       AddTime(1, toadd);
  401. #endif
  402.     } else {  /* Otherwise add on appropriate time vector to chart info. */
  403.       ciCore = ciMain;
  404.       AddTime(mode, toadd);
  405.     }
  406.     ciMain = ciCore;
  407.     if (us.nRel)
  408.       CastRelation(fFalse);
  409.     else
  410.       CastChart(fTrue);
  411.   }
  412. }
  413.  
  414.  
  415. /* This routine exits graphics mode, prompts the user for a set of command */
  416. /* switches, processes them, and returns to the previous graphics with the */
  417. /* new settings in effect, allowing one to change most any setting without */
  418. /* having to lose their graphics state or fall way back to a -Q loop.      */
  419.  
  420. void CommandLineX()
  421. {
  422.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  423.   int argc, fT, fPause = fFalse;
  424.  
  425.   ciCore = ciMain;
  426. #ifdef MSG
  427.   _setvideomode(_DEFAULTMODE);
  428.   _settextrows(gs.nTextRows);
  429. #endif
  430. #ifdef BGI
  431.   restorecrtmode();
  432.   if (gs.nTextRows > 25)
  433.     textmode(C4350);
  434. #endif
  435.   fT = us.fLoop; us.fLoop = fTrue;
  436.   argc = NPromptSwitches(szCommandLine, rgsz);
  437.   is.cchRow = 0;
  438.   is.fSzInteract = fTrue;
  439.   if (!FProcessSwitches(argc, rgsz))
  440.     fPause = fTrue;
  441.   else {
  442.     is.fMult = fFalse;
  443.     FPrintTables();
  444.     if (is.fMult) {
  445.       ClearB((lpbyte)&us.fCredit,
  446.         (int)((lpbyte)&us.fLoop - (lpbyte)&us.fCredit));
  447.       fPause = fTrue;
  448.     }
  449.   }
  450.  
  451. #ifdef PCG
  452.   /* Pause for the user if there was either an error processing the    */
  453.   /* switches, or one of the informational text tables was brought up. */
  454.  
  455.   if (fPause) {
  456.     AnsiColor(kDefault);
  457.     is.cchRow = 0;
  458.     PrintSz("Press any key to return to graphics.\n");
  459.     while (!kbhit())
  460.       ;
  461.     getch();
  462.   }
  463. #endif
  464.   is.fSzInteract = fFalse;
  465.   us.fLoop = fT;
  466.   ciMain = ciCore;
  467.   BeginX();
  468. }
  469.  
  470.  
  471. /* Given two chart size values, adjust them such that the chart will look */
  472. /* "square". We round the higher value down and check certain conditions. */
  473.  
  474. void SquareX(x, y, force)
  475. int *x, *y, force;
  476. {
  477.   if (!force && !fSquare)    /* Unless we want to force a square, realize */
  478.     return;                  /* that some charts look better rectangular. */
  479.   if (*x > *y)
  480.     *x = *y;
  481.   else
  482.     *y = *x;
  483. #ifdef PCG
  484.   if (FEgaRes(gi.nRes))         /* Scale horizontal size if we're in a PC */
  485.     *x = VgaFromEga(*x);        /* graphics mode without "square" pixels. */
  486.   else if (FCgaRes(gi.nRes))
  487.     *x = VgaFromCga(*x);
  488. #endif
  489.   if (fSidebar)      /* Take into account chart's sidebar, if any. */
  490.     *x += xSideT;
  491. }
  492.  
  493.  
  494. #ifndef WIN
  495. /* This routine gets called after graphics are brought up and displayed     */
  496. /* on the screen. It loops, processing key presses, mouse clicks, etc, that */
  497. /* the window receives, until the user specifies they want to exit program. */
  498.  
  499. void InteractX()
  500. {
  501. #ifdef X11
  502.   char sz[cchSzDef];
  503.   XEvent xevent;
  504.   KeySym keysym;
  505.   int fResize = fFalse, fRedraw = fTrue;
  506. #else /* PCG */
  507. #ifdef MOUSE
  508.   int eventx, eventy, eventbtn;
  509. #endif
  510.   int fResize = fTrue, fRedraw = fFalse;
  511. #endif /* PCG */
  512.   int fBreak = fFalse, fPause = fFalse, fCast = fFalse, xcorner = 7,
  513.     mousex = -1, mousey = -1, buttonx = -1, buttony = -1, dir = 1,
  514.     length, key, i;
  515.   bool fT;
  516.   KI coldrw = gi.kiLite;
  517.  
  518.   neg(gs.nAnim);
  519.   while (!fBreak) {
  520.     gi.nScale = gs.nScale/100;
  521.  
  522.     /* Some chart windows, like the world maps and aspect grids, should */
  523.     /* always be a certian size, so correct if a resize was attempted.  */
  524.  
  525.     if (fMap) {
  526.       length = nDegMax*gi.nScale;
  527.       if (gs.xWin != length) {
  528.         gs.xWin = length;
  529.         fResize = fTrue;
  530.       }
  531.       length = nDegHalf*gi.nScale;
  532.       if (gs.yWin != length) {
  533.         gs.yWin = length;
  534.         fResize = fTrue;
  535.       }
  536.     } else if (gi.nMode == gGrid) {
  537.       if (gs.xWin != (length =
  538.         (gs.nGridCell + (us.nRel <= rcDual))*CELLSIZE*gi.nScale+1)) {
  539.         gs.xWin = length;
  540.         fResize = fTrue;
  541.       } if (gs.yWin != length) {
  542.         gs.yWin = length;
  543.         fResize = fTrue;
  544.       }
  545.  
  546.     /* Make sure the window isn't too large or too small. */
  547.  
  548.     } else {
  549.       if (gs.xWin < BITMAPX1) {
  550.         gs.xWin = BITMAPX1;
  551.         fResize = fTrue;
  552.       } else if (gs.xWin > BITMAPX) {
  553.         gs.xWin = BITMAPX;
  554.         fResize = fTrue;
  555.       }
  556.       if (gs.yWin < BITMAPY1) {
  557.         gs.yWin = BITMAPY1;
  558.         fResize = fTrue;
  559.       } else if (gs.yWin > BITMAPY) {
  560.         gs.yWin = BITMAPY;
  561.         fResize = fTrue;
  562.       }
  563.     }
  564.  
  565.     /* If in animation mode, ensure we are in the flicker free resolution. */
  566.  
  567.     if (gs.nAnim < 0) {
  568.       neg(gs.nAnim);
  569. #ifdef PCG
  570.       if (gi.nRes == gs.nResHi && !gs.fJetTrail) {
  571.         gi.nRes = gs.nResLo;
  572.         BeginX();
  573.         gs.xWin = xPcScreen;
  574.         gs.yWin = yPcScreen;
  575.         SquareX(&gs.xWin, &gs.yWin, fFalse);
  576.         fResize = fTrue;
  577.       }
  578. #endif
  579.     }
  580.  
  581.     /* Physically resize window if we've changed the size parameters. */
  582.  
  583.     if (fResize) {
  584.       fResize = fFalse;
  585. #ifdef X11
  586.       XResizeWindow(gi.disp, gi.wind, gs.xWin, gs.yWin);
  587.       XFreePixmap(gi.disp, gi.pmap);
  588.       gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  589. #endif
  590. #ifdef PCG
  591.       if (xPcScreen > gs.xWin)
  592.         gi.xOffset = (xPcScreen - gs.xWin) / 2;
  593.       else {
  594.         if (xcorner % 3 == 1)
  595.           gi.xOffset = 0;
  596.         else if (xcorner % 3 == 0)
  597.           gi.xOffset = -gs.xWin + xPcScreen;
  598.         else
  599.           gi.xOffset = -(gs.xWin - xPcScreen) / 2;
  600.       }
  601.       if (yPcScreen > gs.yWin)
  602.         gi.yOffset = (yPcScreen - gs.yWin) / 2;
  603.       else {
  604.         if (xcorner > 6)
  605.           gi.yOffset = 0;
  606.         else if (xcorner < 4)
  607.           gi.yOffset = -gs.yWin + yPcScreen;
  608.         else
  609.           gi.yOffset = -(gs.yWin - yPcScreen) / 2;
  610.       }
  611. #endif
  612.       fRedraw = fTrue;
  613.     }
  614.  
  615.     /* Recast chart if the chart information has changed any. */
  616.  
  617.     if (fCast) {
  618.       fCast = fFalse;
  619.       ciCore = ciMain;
  620.       if (us.nRel)
  621.         CastRelation(fFalse);
  622.       else
  623.         CastChart(fTrue);
  624.       fRedraw = fTrue;
  625.     }
  626.     if (gs.nAnim && !fPause)
  627.       fRedraw = fTrue;
  628.  
  629.     /* Update the screen if anything has changed since last time around. */
  630.  
  631.     if (fRedraw) {
  632.       fRedraw = fFalse;
  633.  
  634.       /* If we're in animation mode, change the chart info appropriately. */
  635.  
  636.       if (gs.nAnim && !fPause)
  637.         Animate(gs.nAnim, dir);
  638.  
  639.       /* Clear the screen and set up a buffer to draw in. */
  640.  
  641. #ifdef X11
  642.       XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  643. #endif
  644. #ifdef PCG
  645. #ifdef MOUSE
  646.       MouseShow(fFalse);
  647. #endif
  648. #ifdef MSG
  649.       if (gi.cfg.numvideopages > 1)
  650.         _setactivepage(_getactivepage() == gs.fJetTrail);
  651. #else
  652.       if (gi.nPages > 1) {
  653.         gi.nPageCur = (gi.nPageCur == gs.fJetTrail);
  654.         setactivepage(gi.nPageCur);
  655.       }
  656. #endif
  657. #endif /* PCG */
  658.  
  659.       DrawChartX();
  660.  
  661.       /* Make the drawn chart visible in the current screen buffer. */
  662.  
  663. #ifdef X11
  664.       XSync(gi.disp, 0);
  665.       XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  666.         0, 0, gs.xWin, gs.yWin, 0, 0);
  667. #endif
  668. #ifdef PCG
  669. #ifdef MSG
  670.       if (gi.cfg.numvideopages > 1)
  671.         _setvisualpage(_getactivepage());
  672. #else
  673.       if (gi.nPages > 1)
  674.         setvisualpage(gi.nPageCur);
  675. #endif
  676. #ifdef MOUSE
  677.       if (!gs.nAnim || fPause)
  678.         MouseShow(fTrue);
  679. #endif
  680. #endif /* PCG */
  681.     }  /* if */
  682.  
  683.     /* Now process what's on the event queue, i.e. any keys pressed, etc. */
  684.  
  685. #ifdef X11
  686.     if (XEventsQueued(gi.disp, QueuedAfterFlush /*QueuedAfterReading*/) ||
  687.       !gs.nAnim || fPause) {
  688.       XNextEvent(gi.disp, &xevent);
  689.  
  690.       /* Restore what's on window if a part of it gets uncovered. */
  691.  
  692.       if (xevent.type == Expose && xevent.xexpose.count == 0) {
  693.         XSync(gi.disp, 0);
  694.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  695.           0, 0, gs.xWin, gs.yWin, 0, 0);
  696.       }
  697.       switch (xevent.type) {
  698.  
  699.       /* Check for a manual resize of window by user. */
  700.  
  701.       case ConfigureNotify:
  702.         gs.xWin = xevent.xconfigure.width;
  703.         gs.yWin = xevent.xconfigure.height;
  704.         XFreePixmap(gi.disp, gi.pmap);
  705.         gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  706.         fRedraw = fTrue;
  707.         break;
  708.       case MappingNotify:
  709.         XRefreshKeyboardMapping((XMappingEvent *)&xevent);
  710.         break;
  711.  
  712. #ifdef MOUSE
  713.       /* Process any mouse buttons the user pressed. */
  714.  
  715.       case ButtonPress:
  716.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  717.         if (xevent.xbutton.button == Button1) {
  718.           DrawColor(gi.kiLite);
  719.           DrawPoint(mousex, mousey);
  720.           XSync(gi.disp, 0);
  721.           XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  722.             0, 0, gs.xWin, gs.yWin, 0, 0);
  723.         } else if (xevent.xbutton.button == Button2 && (gi.nMode ==
  724.           gAstroGraph || gi.nMode == gWorldMap) && gs.nRot == 0) {
  725.           Lon = DegToDec(rDegHalf -
  726.             (real)(xevent.xbutton.x-1)/(real)(gs.xWin-2)*rDegMax);
  727.           Lat = DegToDec(rDegQuad -
  728.             (real)(xevent.xbutton.y-1)/(real)(gs.yWin-2)*181.0);
  729.           sprintf(sz, "Mouse is at %s.", SzLocation(Lon, Lat));
  730.           PrintNotice(sz);
  731.         } else if (xevent.xbutton.button == Button3)
  732.           fBreak = fTrue;
  733.         break;
  734.  
  735.       /* Check for user dragging any of the mouse buttons across window. */
  736.  
  737.       case MotionNotify:
  738.         DrawColor(coldrw);
  739.         DrawLine(mousex, mousey, xevent.xbutton.x, xevent.xbutton.y);
  740.         XSync(gi.disp, 0);
  741.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  742.           0, 0, gs.xWin, gs.yWin, 0, 0);
  743.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  744.         break;
  745. #endif
  746.  
  747.       /* Process any keys user pressed in window. */
  748.  
  749.       case KeyPress:
  750.         length = XLookupString((XKeyEvent *)&xevent, xkey, 10, &keysym, 0);
  751.         if (length == 1) {
  752.           key = xkey[0];
  753. #endif /* X11 */
  754. #ifdef PCG
  755. #ifdef MOUSE
  756.       if ((!gs.nAnim || fPause) && MouseStatus(&eventx, &eventy, &eventbtn)) {
  757.  
  758.         /* If the left button is down, draw on the screen. */
  759.         if (eventbtn == mfLeft && mousex >= 0) {
  760.           MouseShow(fFalse);
  761.           DrawColor(coldrw);
  762.           PcMoveTo(mousex, mousey);
  763.           buttonx = eventx; buttony = eventy;
  764.           PcLineTo(buttonx, buttony);
  765.  
  766.         /* If the right button is down, change the default location. */
  767.         } else if (eventbtn == mfRight) {
  768.           if (fMap && gs.nRot == 0 && !gs.fConstel && !gs.fMollewide) {
  769.             Lon = DegToDec(rDegHalf-(real)(eventx-gi.xOffset)/
  770.               (real)gs.xWin*rDegMax);
  771.             if (Lon < -rDegHalf)
  772.               Lon = -rDegHalf;
  773.             else if (Lon > rDegHalf)
  774.               Lon = rDegHalf;
  775.             Lat = DegToDec(rDegQuad-(real)(eventy-gi.yOffset)/
  776.               (real)gs.yWin*181.0);
  777.             if (Lat < -rDegQuad)
  778.               Lat = -rDegQuad;
  779.             else if (Lat > rDegQuad)
  780.               Lat = rDegQuad;
  781.             fCast = fTrue;
  782.  
  783.           /* Right button means draw lines if not in a world map mode. */
  784.           } else if (buttonx >= 0) {
  785.             MouseShow(fFalse);
  786.             DrawColor(coldrw);
  787.             PcMoveTo(buttonx, buttony);
  788.             PcLineTo(eventx, eventy);
  789.           }
  790.  
  791.         /* Middle button (which most PC's don't have) means exit program. */
  792.         } else if (eventbtn == mfMiddle)
  793.           fBreak = fTrue;
  794.  
  795.         mousex = eventx; mousey = eventy;
  796.         MouseShow(fTrue);
  797.       } else
  798. #endif /* MOUSE */
  799.         if (kbhit()) {
  800.           key = getch();
  801. #endif /* PCG */
  802. LSwitch:
  803.           switch (key) {
  804. #ifdef PCG
  805.           case chNull:
  806.             key = NFromAltN(getch());
  807.             goto LSwitch;
  808. #endif
  809.           case ' ':
  810.             fRedraw = fTrue;
  811.             break;
  812.           case 'p':
  813.             not(fPause);
  814.             break;
  815.           case 'r':
  816.             neg(dir);
  817.             break;
  818.           case 'x':
  819.             not(gs.fInverse);
  820.             InitColorsX();
  821.             fRedraw = fTrue;
  822.             break;
  823.           case 'm':
  824.             if (!gi.fMono) {
  825.               not(gs.fColor);
  826. #ifdef MSG
  827.               _getvideoconfig((struct videoconfig far *) &gi.cfg);
  828. #endif
  829.               InitColorsX();
  830.               fRedraw = fTrue;
  831.             }
  832.             break;
  833.           case 'B':
  834. #ifdef X11
  835.             XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  836.             XClearWindow(gi.disp, gi.root);
  837. #endif
  838. #ifdef PCG
  839.             gs.xWin = xPcScreen;
  840.             gs.yWin = yPcScreen;
  841.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  842.             fResize = fTrue;
  843. #endif
  844.             break;
  845.           case 't':
  846.             not(gs.fText);
  847.             fRedraw = fTrue;
  848.             break;
  849.           case 'i':
  850.             not(gs.fAlt);
  851.             fRedraw = fTrue;
  852.             break;
  853.           case 'b':
  854.             not(gs.fBorder);
  855.             fRedraw = fTrue;
  856.             break;
  857.           case 'l':
  858.             not(gs.fLabel);
  859.             fRedraw = fTrue;
  860.             break;
  861.           case 'j':
  862.             not(gs.fJetTrail);
  863.             break;
  864.           case '<':
  865.             if (gs.nScale > 100) {
  866.               gs.nScale -= 100;
  867.               fResize = fTrue;
  868.             }
  869.             break;
  870.           case '>':
  871.             if (gs.nScale < MAXSCALE) {
  872.               gs.nScale += 100;
  873.               fResize = fTrue;
  874.             }
  875.             break;
  876.           case '[':
  877.             if (gi.nMode == gGlobe && gs.rTilt > -rDegQuad) {
  878.               gs.rTilt = gs.rTilt > -rDegQuad ? gs.rTilt-TILTSTEP : -rDegQuad;
  879.               fRedraw = fTrue;
  880.             }
  881.             break;
  882.           case ']':
  883.             if (gi.nMode == gGlobe && gs.rTilt < rDegQuad) {
  884.               gs.rTilt = gs.rTilt < rDegQuad ? gs.rTilt+TILTSTEP : rDegQuad;
  885.               fRedraw = fTrue;
  886.             }
  887.             break;
  888.           case 'Q':
  889.             SquareX(&gs.xWin, &gs.yWin, fTrue);
  890.             fResize = fTrue;
  891.             break;
  892.           case 'R':
  893.             for (i = oChi; i <= oVes; i++)
  894.               not(ignore[i]);
  895.             for (i = oLil; i <= oEP; i++)
  896.               not(ignore[i]);
  897.             fCast = fTrue;
  898.             break;
  899.           case 'C':
  900.             not(us.fCusp);
  901.             for (i = cuspLo; i <= cuspHi; i++)
  902.               ignore[i] = !us.fCusp || !ignore[i];
  903.             fCast = fTrue;
  904.             break;
  905.           case 'u':
  906.             not(us.fUranian);
  907.             for (i = uranLo; i <= uranHi; i++)
  908.               ignore[i] = !us.fUranian || !ignore[i];
  909.             fCast = fTrue;
  910.             break;
  911.           case 'U':
  912.             us.nStar = !us.nStar;
  913.             for (i = starLo; i <= starHi; i++)
  914.               ignore[i] = !us.nStar || !ignore[i];
  915.             fCast = fTrue;
  916.             break;
  917.           case 'c':
  918.             us.nRel = us.nRel ? 0 : rcDual;
  919.             fCast = fTrue;
  920.             break;
  921.           case 's':
  922.             not(us.fSidereal);
  923.             fCast = fTrue;
  924.             break;
  925.           case 'h':
  926.             us.objCenter = us.objCenter ? 0 : 1;
  927.             fCast = fTrue;
  928.             break;
  929.           case 'f':
  930.             not(us.fFlip);
  931.             fCast = fTrue;
  932.             break;
  933.           case 'g':
  934.             not(us.fDecan);
  935.             fCast = fTrue;
  936.             break;
  937.           case '+':
  938.             Animate(gs.nAnim, abs(dir));
  939.             fCast = fTrue;
  940.             break;
  941.           case '-':
  942.             Animate(gs.nAnim, -abs(dir));
  943.             fCast = fTrue;
  944.             break;
  945.           case 'o':
  946.             ciSave = ciMain;
  947.             break;
  948.           case 'O':
  949.             ciMain = ciSave;
  950.             fCast = fTrue;
  951.             break;
  952. #ifdef TIME
  953.           case 'n':
  954.             FInputData(szNowCore);
  955.             ciMain = ciCore;
  956.             fCast = fTrue;
  957.             break;
  958. #endif
  959.           case 'N':                     /* The continuous update animation. */
  960.             gs.nAnim = gs.nAnim ? 0 : -10;
  961.             break;
  962.  
  963.           /* These are the nine different "add time to chart" animations. */
  964.           case '!': gs.nAnim = -1; break;
  965.           case '@': gs.nAnim = -2; break;
  966.           case '#': gs.nAnim = -3; break;
  967.           case '$': gs.nAnim = -4; break;
  968.           case '%': gs.nAnim = -5; break;
  969.           case '^': gs.nAnim = -6; break;
  970.           case '&': gs.nAnim = -7; break;
  971.           case '*': gs.nAnim = -8; break;
  972.           case '(': gs.nAnim = -9; break;
  973.  
  974.           /* Should we go switch to a new chart type? */
  975.           case 'V': gi.nMode = gWheel;      fRedraw = fTrue; break;
  976.           case 'A': gi.nMode = gGrid;       fRedraw = fTrue; break;
  977.           case 'Z': gi.nMode = gHorizon;    fRedraw = fTrue; break;
  978.           case 'S': gi.nMode = gOrbit;      fRedraw = fTrue; break;
  979.           case 'J': gi.nMode = gDisposit;   fRedraw = fTrue; break;
  980.           case 'L': gi.nMode = gAstroGraph; fRedraw = fTrue; break;
  981.           case 'K': gi.nMode = gCalendar;   fRedraw = fTrue; break;
  982.           case 'E': gi.nMode = gEphemeris;  fRedraw = fTrue; break;
  983.           case 'W': gi.nMode = gWorldMap;   fRedraw = fTrue; break;
  984.           case 'G': gi.nMode = gGlobe;      fRedraw = fTrue; break;
  985.           case 'P': gi.nMode = gPolar;      fRedraw = fTrue; break;
  986. #ifdef BIORHYTHM
  987.           case 'Y':            /* Should we switch to biorhythm chart? */
  988.             us.nRel = rcBiorhythm;
  989.             gi.nMode = gBiorhythm;
  990.             fCast = fTrue;
  991.             break;
  992. #endif
  993. #ifdef CONSTEL
  994.           case 'F':
  995.             if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  996.               gi.nMode = gWorldMap;
  997.             not(gs.fConstel);
  998.             fRedraw = fTrue;
  999.             break;
  1000. #endif
  1001.           case '0':
  1002.             not(us.fPrimeVert);
  1003.             not(us.fCalendarYear);
  1004.             not(us.nEphemYears);
  1005.             not(gs.fMollewide);
  1006.             gi.nMode = (gi.nMode == gWheel ? gHouse :
  1007.               (gi.nMode == gHouse ? gWheel : gi.nMode));
  1008.             fRedraw = fTrue;
  1009.             break;
  1010.           case 'v': case 'H': case '?':
  1011. #ifdef MSG
  1012.             _setvideomode(_DEFAULTMODE);
  1013.             if (key != 'v')
  1014.               _settextrows(50);
  1015. #endif
  1016. #ifdef BGI
  1017.             restorecrtmode();
  1018.             if (key != 'v')
  1019.               textmode(C4350);
  1020. #endif
  1021.             length = us.nScrollRow;
  1022.             us.nScrollRow = 0;
  1023.             if (key == 'v')
  1024.               ChartListing();
  1025.             else
  1026.               DisplayKeysX();
  1027.             us.nScrollRow = length;
  1028. #ifdef PCG
  1029.             while (!kbhit())
  1030.               ;
  1031.             key = getch();
  1032.             if (key == 'q' || key == chEscape || key == chBreak) {
  1033.               fBreak = fTrue;
  1034.               break;
  1035.             }
  1036.             BeginX();
  1037.             fResize = fTrue;
  1038. #endif
  1039.             break;
  1040.           case chReturn:
  1041.             CommandLineX();
  1042.             fResize = fCast = fTrue;
  1043.             break;
  1044. #ifdef PCG
  1045.           case chTab:
  1046.             if (gi.nRes == gs.nResHi)
  1047.               gi.nRes = gs.nResLo;
  1048.             else
  1049.               gi.nRes = gs.nResHi;
  1050.             BeginX();
  1051.             gs.xWin = xPcScreen;
  1052.             gs.yWin = yPcScreen;
  1053.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  1054.             fResize = fTrue;
  1055.             break;
  1056. #endif
  1057.           case chDelete:
  1058. #ifdef PCG
  1059. #ifdef MOUSE
  1060.             MouseShow(fFalse);
  1061. #endif
  1062. #endif /* PCG */
  1063.             fT = gs.fJetTrail;
  1064.             gs.fJetTrail = fFalse;
  1065.             DrawClearScreen();
  1066.             gs.fJetTrail = fT;
  1067.             break;
  1068. #ifdef MOUSE
  1069.           case 'z'-'`': coldrw = kBlack;   break;
  1070.           case 'e'-'`': coldrw = kMaroon;  break;
  1071.           case 'f'-'`': coldrw = kDkGreen; break;
  1072.           case 'o'-'`': coldrw = kOrange;  break;
  1073.           case 'n'-'`': coldrw = kDkBlue;  break;
  1074.           case 'u'-'`': coldrw = kPurple;  break;
  1075.           case 'k'-'`': coldrw = kDkCyan;  break;
  1076.           case 'l'-'`': coldrw = kLtGray;  break;
  1077.           case 'd'-'`': coldrw = kDkGray;  break;
  1078.           case 'r'-'`': coldrw = kRed;     break;
  1079.           case 'g'-'`': coldrw = kGreen;   break;
  1080.           case 'y'-'`': coldrw = kYellow;  break;
  1081.           case 'b'-'`': coldrw = kBlue;    break;
  1082.           case 'v'-'`': coldrw = kMagenta; break;
  1083.           case 'j'-'`': coldrw = kCyan;    break;
  1084.           case 'a'-'`': coldrw = kWhite;   break;
  1085. #ifdef PCG
  1086.           case 't'-'`':
  1087.             MouseShow(fFalse);
  1088.             if (buttonx >= 0)
  1089. #ifdef MSG
  1090.               _rectangle(_GBORDER, buttonx, buttony, mousex, mousey);
  1091. #else
  1092.               DrawEdge(Min(buttonx, mousex) - gi.xOffset,
  1093.                 Min(buttony, mousey) - gi.yOffset,
  1094.                 Max(mousex, buttonx) - gi.xOffset,
  1095.                 Max(mousey, buttony) - gi.yOffset);
  1096. #endif
  1097.             MouseShow(fTrue);
  1098.             break;
  1099.           case 'x'-'`':
  1100.             MouseShow(fFalse);
  1101.             if (buttonx >= 0)
  1102. #ifdef MSG
  1103.               _ellipse(_GBORDER, buttonx, buttony, mousex, mousey);
  1104. #else
  1105.               DrawEllipse(Min(buttonx, mousex) - gi.xOffset,
  1106.                 Min(buttony, mousey) - gi.yOffset,
  1107.                 Max(mousex, buttonx) - gi.xOffset,
  1108.                 Max(mousey, buttony) - gi.yOffset);
  1109. #endif
  1110.             MouseShow(fTrue);
  1111.             break;
  1112. #endif /* PCG */
  1113. #endif /* MOUSE */
  1114.           case 'q': case chEscape: case chBreak:
  1115.             fBreak = fTrue;
  1116.             break;
  1117.           default:
  1118.             if (key > '0' && key <= '9') {
  1119. #ifdef PCG
  1120.               if (gs.nAnim && !fPause)
  1121. #endif
  1122.                 /* Process numbers 1..9 signifying animation rate. */
  1123.                 dir = (dir > 0 ? 1 : -1)*(key-'0');
  1124. #ifdef PCG
  1125.               else {
  1126.                 /* If we aren't in animation mode, then 1..9 refers to the */
  1127.                 /* clipping "quadrant" to use if chart size > screen size. */
  1128.                 xcorner = key-'0';
  1129.                 fResize = fTrue;
  1130.               }
  1131. #endif
  1132.               break;
  1133.             } else if (FBetween(key, 201, 248)) {
  1134.               is.fSzInteract = fTrue;
  1135.               if (szMacro[key-201]) {
  1136.                 FProcessCommandLine(szMacro[key-201]);
  1137.                 fResize = fCast = fTrue;
  1138.               }
  1139.               is.fSzInteract = fFalse;
  1140.               break;
  1141.             }
  1142.             putchar(chBell);    /* Any key not bound will sound a beep. */
  1143.           }  /* switch */
  1144.         }  /* if */
  1145. #ifdef X11
  1146.       default:
  1147.         ;
  1148.       }  /* switch */
  1149.     }  /* if */
  1150. #endif
  1151.   }  /* while */
  1152. }
  1153.  
  1154.  
  1155. /* This is called right before program termination to get rid of the window. */
  1156.  
  1157. void EndX()
  1158. {
  1159. #ifdef X11
  1160.   XFreeGC(gi.disp, gi.gc);
  1161.   XFreeGC(gi.disp, gi.pmgc);
  1162.   XFreePixmap(gi.disp, gi.pmap);
  1163.   XDestroyWindow(gi.disp, gi.wind);
  1164.   XCloseDisplay(gi.disp);
  1165. #endif
  1166. #ifdef MSG
  1167.   _setvideomode(_DEFAULTMODE);
  1168. #endif
  1169. #ifdef BGI
  1170.   restorecrtmode();
  1171. #endif
  1172. }
  1173. #endif /* ISG */
  1174. #endif /* WIN */
  1175.  
  1176.  
  1177. /*
  1178. ******************************************************************************
  1179. ** Main Graphics Processing.
  1180. ******************************************************************************
  1181. */
  1182.  
  1183. /* Process one command line switch passed to the program dealing with the    */
  1184. /* graphics features. This is just like the processing of each switch in the */
  1185. /* main program, however here each switch has been prefixed with an 'X'.     */
  1186.  
  1187. int NProcessSwitchesX(argc, argv, pos, fOr, fAnd, fNot)
  1188. int argc, pos;
  1189. bool fOr, fAnd, fNot;
  1190. char **argv;
  1191. {
  1192.   int darg = 0, i, j;
  1193.   real rT;
  1194.   char ch1;
  1195.  
  1196.   ch1 = argv[0][pos+1];
  1197.   switch (argv[0][pos]) {
  1198.   case chNull:
  1199.     break;
  1200.  
  1201.   case 'b':
  1202.     if (us.fNoWrite || is.fSzInteract) {
  1203.       ErrorArgv("Xb");
  1204.       return tcError;
  1205.     }
  1206.     ch1 = ChCap(ch1);
  1207.     if (FValidBmpmode(ch1))
  1208.       gs.chBmpMode = ch1;
  1209.     SwitchF2(gs.fBitmap);
  1210.     gs.fPS = gs.fMeta = fFalse;
  1211.     break;
  1212.  
  1213. #ifdef PS
  1214.   case 'p':
  1215.     if (us.fNoWrite || is.fSzInteract) {
  1216.       ErrorArgv("Xp");
  1217.       return tcError;
  1218.     }
  1219.     gs.fPS = fTrue + (ch1 != '0');
  1220.     gs.fBitmap = gs.fMeta = fFalse;
  1221.     break;
  1222. #endif
  1223.  
  1224. #ifdef META
  1225.   case 'M':
  1226.     if (us.fNoWrite || is.fSzInteract) {
  1227.       ErrorArgv("XM");
  1228.       return tcError;
  1229.     }
  1230.     if (ch1 == '0')
  1231.       SwitchF(gs.fFont);
  1232.     SwitchF2(gs.fMeta);
  1233.     gs.fBitmap = gs.fPS = fFalse;
  1234.     break;
  1235. #endif
  1236.  
  1237.   case 'o':
  1238.     if (us.fNoWrite || is.fSzInteract) {
  1239.       ErrorArgv("Xo");
  1240.       return tcError;
  1241.     }
  1242.     if (argc <= 1) {
  1243.       ErrorArgc("Xo");
  1244.       return tcError;
  1245.     }
  1246.     if (!gs.fBitmap && !gs.fPS && !gs.fMeta)
  1247.       gs.fBitmap = fTrue;
  1248.     gi.szFileOut = SzPersist(argv[1]);
  1249.     darg++;
  1250.     break;
  1251.  
  1252. #ifdef X11
  1253.   case 'B':
  1254.     if (is.fSzInteract) {
  1255.       ErrorArgv("XB");
  1256.       return tcError;
  1257.     }
  1258.     SwitchF(gs.fRoot);
  1259.     break;
  1260. #endif
  1261.  
  1262.   case 'm':
  1263.     SwitchF(gs.fColor);
  1264.     break;
  1265.  
  1266.   case 'r':
  1267.     SwitchF(gs.fInverse);
  1268.     break;
  1269.  
  1270.   case 'w':
  1271.     if (argc <= 1) {
  1272.       ErrorArgc("Xw");
  1273.       return tcError;
  1274.     }
  1275.     i = atoi(argv[1]);
  1276.     if (argc > 2 && ((j = atoi(argv[2])) || argv[2][0] == '0')) {
  1277.       argc--; argv++;
  1278.       darg++;
  1279.     } else
  1280.       j = i;
  1281.     if (!FValidGraphx(i)) {
  1282.       ErrorValN("Xw", i);
  1283.       return tcError;
  1284.     }
  1285.     if (!FValidGraphy(j)) {
  1286.       ErrorValN("Xw", j);
  1287.       return tcError;
  1288.     }
  1289.     gs.xWin = i; gs.yWin = j;
  1290.     darg++;
  1291.     break;
  1292.  
  1293.   case 's':
  1294.     if (argc <= 1) {
  1295.       ErrorArgc("Xs");
  1296.       return tcError;
  1297.     }
  1298.     i = atoi(argv[1]);
  1299.     if (i < 100)
  1300.       i *= 100;
  1301.     if (!FValidScale(i)) {
  1302.       ErrorValN("Xs", i);
  1303.       return tcError;
  1304.     }
  1305.     gs.nScale = i;
  1306.     darg++;
  1307.     break;
  1308.  
  1309.   case 'i':
  1310.     SwitchF(gs.fAlt);
  1311.     break;
  1312.  
  1313.   case 't':
  1314.     SwitchF(gs.fText);
  1315.     break;
  1316.  
  1317.   case 'u':
  1318.     SwitchF(gs.fBorder);
  1319.     break;
  1320.  
  1321.   case 'l':
  1322.     SwitchF(gs.fLabel);
  1323.     break;
  1324.  
  1325.   case 'j':
  1326.     SwitchF(gs.fJetTrail);
  1327.     break;
  1328.  
  1329.   case '1':
  1330.     if (argc <= 1) {
  1331.       ErrorArgc("X1");
  1332.       return tcError;
  1333.     }
  1334.     i = NParseSz(argv[1], pmObject);
  1335.     if (!FItem(i)) {
  1336.       ErrorValN("X1", i);
  1337.       return tcError;
  1338.     }
  1339.     gs.objLeft = i;
  1340.     darg++;
  1341.     break;
  1342.  
  1343.   case '2':
  1344.     if (argc <= 1) {
  1345.       ErrorArgc("X2");
  1346.       return tcError;
  1347.     }
  1348.     i = NParseSz(argv[1], pmObject);
  1349.     if (!FItem(i)) {
  1350.       ErrorValN("X2", i);
  1351.       return tcError;
  1352.     }
  1353.     gs.objLeft = -i;
  1354.     darg++;
  1355.     break;
  1356.  
  1357. #ifdef X11
  1358.   case 'd':
  1359.     if (is.fSzInteract) {
  1360.       ErrorArgv("Xd");
  1361.       return tcError;
  1362.     }
  1363.     if (argc <= 1) {
  1364.       ErrorArgc("Xd");
  1365.       return tcError;
  1366.     }
  1367.     gs.szDisplay = SzPersist(argv[1]);
  1368.     darg++;
  1369.     break;
  1370. #endif
  1371.  
  1372.   case 'W':
  1373.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1374.       darg++;
  1375.       if (!FValidRotation(i)) {
  1376.         ErrorValN("XW", i);
  1377.         return tcError;
  1378.       }
  1379.       gs.nRot = i;
  1380.     }
  1381.     gi.nMode = gWorldMap;
  1382.     if (ch1 == '0')
  1383.       gs.fMollewide = fTrue;
  1384.     is.fHaveInfo = fTrue;
  1385.     break;
  1386.  
  1387.   case 'G':
  1388.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1389.       darg++;
  1390.       if (!FValidRotation(i)) {
  1391.         ErrorValN("XG", i);
  1392.         return tcError;
  1393.       }
  1394.       gs.nRot = i;
  1395.       if (argc > 2 && ((rT = atof(argv[2])) || argv[2][0] == '0')) {
  1396.         darg++;
  1397.         if (!FValidTilt(rT)) {
  1398.           ErrorValR("XG", rT);
  1399.           return tcError;
  1400.         }
  1401.         gs.rTilt = rT;
  1402.       }
  1403.     }
  1404.     gi.nMode = gGlobe;
  1405.     is.fHaveInfo = fTrue;
  1406.     break;
  1407.  
  1408.   case 'P':
  1409.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1410.       darg++;
  1411.       if (!FValidRotation(i)) {
  1412.         ErrorValN("XP", i);
  1413.         return tcError;
  1414.       }
  1415.     } else
  1416.       i = 0;
  1417.     gs.nRot = i;
  1418.     gi.nMode = gPolar;
  1419.     if (ch1 == '0')
  1420.       gs.fPrintMap = fTrue;
  1421.     is.fHaveInfo = fTrue;
  1422.     break;
  1423.  
  1424. #ifdef CONSTEL
  1425.   case 'F':
  1426.     if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  1427.       gi.nMode = gWorldMap;
  1428.     not(gs.fConstel);
  1429.     is.fHaveInfo = fTrue;
  1430.     break;
  1431. #endif
  1432.  
  1433. #ifdef ISG
  1434.   case 'n':
  1435.     if (argc > 1 && (i = atoi(argv[1])))
  1436.       darg++;
  1437.     else
  1438.       i = 10;
  1439.     if (i < 1 || i > 10) {
  1440.       ErrorValN("Xn", i);
  1441.       return tcError;
  1442.     }
  1443.     gs.nAnim = i;
  1444.     break;
  1445. #endif
  1446.  
  1447.   default:
  1448.     ErrorSwitch(argv[0]);
  1449.     return tcError;
  1450.   }
  1451.   /* 'darg' contains the value to be added to argc when we return. */
  1452.   return darg;
  1453. }
  1454.  
  1455.  
  1456. /* Process one command line switch passed to the program dealing with more  */
  1457. /* obscure graphics options. This is structured very much like the function */
  1458. /* NProcessSwitchesX(), except here we know each switch begins with 'YX'.   */
  1459.  
  1460. int NProcessSwitchesRareX(argc, argv, pos)
  1461. int argc, pos;
  1462. char **argv;
  1463. {
  1464.   int darg = 0, i, j;
  1465.   char ch1;
  1466.  
  1467.   ch1 = argv[0][pos+1];
  1468.   switch (argv[0][pos]) {
  1469.   case chNull:
  1470.     if (argc <= 2) {
  1471.       ErrorArgc("YX");
  1472.       return tcError;
  1473.     }
  1474. #ifdef PCG
  1475.     i = atoi(argv[1]);
  1476.     if (!FValidResmode(i)) {
  1477.       ErrorValN("YX", i);
  1478.       return tcError;
  1479.     }
  1480.     gs.nResHi = i;
  1481.     i = atoi(argv[2]);
  1482.     if (!FValidResmode(i)) {
  1483.       ErrorValN("YX", i);
  1484.       return tcError;
  1485.     }
  1486.     gs.nResLo = i;
  1487.     gs.fBitmap = gs.fPS = gs.fMeta = fFalse;
  1488. #endif
  1489.     darg += 2;
  1490.     break;
  1491.  
  1492.   case 'G':
  1493.     if (argc <= 1) {
  1494.       ErrorArgc("YXG");
  1495.       return tcError;
  1496.     }
  1497.     i = atoi(argv[1]);
  1498.     if (!FValidGlyphs(i)) {
  1499.       ErrorValN("YXg", i);
  1500.       return tcError;
  1501.     }
  1502.     gs.nGlyphs = i;
  1503.     j = i/1000;
  1504.     if (FBetween(j, 1, 2))
  1505.       szDrawSign[sCap] = szDrawSign[cSign+j];
  1506.     j = (i/100)%10;
  1507.     if (FBetween(j, 1, 2))
  1508.       szDrawObject[oUra] = szDrawObject[oNorm+j];
  1509.     j = (i/10)%10;
  1510.     if (FBetween(j, 1, 2))
  1511.       szDrawObject[oPlu] = szDrawObject[oNorm+2+j];
  1512.     j = i%10;
  1513.     if (FBetween(j, 1, 3))
  1514.       szDrawObject[oLil] = szDrawObject[oNorm+4+j];
  1515.     darg++;
  1516.     break;
  1517.  
  1518.   case 'g':
  1519.     if (argc <= 1) {
  1520.       ErrorArgc("YXg");
  1521.       return tcError;
  1522.     }
  1523.     i = atoi(argv[1]);
  1524.     if (!FValidGrid(i)) {
  1525.       ErrorValN("YXg", i);
  1526.       return tcError;
  1527.     }
  1528.     gs.nGridCell = i;
  1529.     darg++;
  1530.     break;
  1531.  
  1532.   case 'f':
  1533.     if (argc <= 1) {
  1534.       ErrorArgc("YXf");
  1535.       return tcError;
  1536.     }
  1537.     gs.fFont = atoi(argv[1]);
  1538.     darg++;
  1539.     break;
  1540.  
  1541. #ifdef PS
  1542.   case 'p':
  1543.     if (ch1 == '0') {
  1544.       if (argc <= 2) {
  1545.         ErrorArgc("YXp0");
  1546.         return tcError;
  1547.       }
  1548.       gs.xInch = atof(argv[1]);
  1549.       gs.yInch = atof(argv[2]);
  1550.       darg += 2;
  1551.       break;
  1552.     }
  1553.     if (argc <= 1) {
  1554.       ErrorArgc("YXp");
  1555.       return tcError;
  1556.     }
  1557.     gs.nOrient = atoi(argv[1]);
  1558.     darg++;
  1559.     break;
  1560. #endif
  1561.  
  1562.   default:
  1563.     ErrorSwitch(argv[0]);
  1564.     return tcError;
  1565.   }
  1566.   /* 'darg' contains the value to be added to argc when we return. */
  1567.   return darg;
  1568. }
  1569.  
  1570.  
  1571. /* This is the main interface to all the graphics features. This routine     */
  1572. /* is called from the main program if any of the -X switches were specified, */
  1573. /* and it sets up for and goes and generates the appropriate graphics chart. */
  1574. /* We return fTrue if successfull, fFalse if some non-fatal error occurred.  */
  1575.  
  1576. bool FActionX()
  1577. {
  1578.   int i;
  1579.  
  1580.   /* Set up variables in preparation for graphics. Set the glyphs for     */
  1581.   /* certain objects to point to their current setting, and if doing      */
  1582.   /* constellations, give a couple stars more correct astronomical names. */
  1583.  
  1584. #ifdef CONSTEL
  1585.   if (gs.fConstel) {
  1586.     szObjName[starLo-1+10] = "Alnilam";  /* Normally "Orion"     */
  1587.     szObjName[starLo-1+47] = "M31";      /* Normally "Andromeda" */
  1588.   }
  1589. #endif
  1590.   i = gs.nGlyphs/1000;
  1591.   szDrawSign[sCap] = szDrawSign[cSign+(i == 2 ? 2 : 1)];
  1592.   i = (gs.nGlyphs/100)%10;
  1593.   szDrawObject[oUra] = szDrawObject[oNorm+(i == 2 ? 2 : 1)];
  1594.   i = (gs.nGlyphs/10)%10;
  1595.   szDrawObject[oPlu] = szDrawObject[oNorm+2+(i == 2 ? 2 : 1)];
  1596.   i = gs.nGlyphs%10;
  1597.   szDrawObject[oLil] =
  1598.     szDrawObject[oNorm+4+(FBetween(i, 2, 3) ? i : fSouthNode ? 3 : 1)];
  1599. #ifdef STROKE
  1600.   if (fSouthNode)
  1601.     szObjectFont[oSou] = '>';
  1602. #endif
  1603.   gi.fFile = (gs.fBitmap || gs.fPS || gs.fMeta);
  1604. #ifdef PS
  1605.   gi.fEps = gs.fPS > fTrue;
  1606. #endif
  1607.  
  1608.   /* First figure out what graphic mode to generate the chart in, based on */
  1609.   /* various non-X command switches, e.g. -L combined with -X, -g combined */
  1610.   /* with -X, and so on, and determine the size the window is to be, too.  */
  1611.  
  1612.   if (gi.nMode == 0) {
  1613.     if (us.fWheel)
  1614.       gi.nMode = gHouse;
  1615.     else if (us.fGrid || us.fMidpoint)
  1616.       gi.nMode = gGrid;
  1617.     else if (us.fHorizon)
  1618.       gi.nMode = gHorizon;
  1619.     else if (us.fOrbit)
  1620.       gi.nMode = gOrbit;
  1621.     else if (us.fInfluence)
  1622.       gi.nMode = gDisposit;
  1623.     else if (us.fAstroGraph)
  1624.       gi.nMode = gAstroGraph;
  1625.     else if (us.fCalendar)
  1626.       gi.nMode = gCalendar;
  1627.     else if (us.fEphemeris)
  1628.       gi.nMode = gEphemeris;
  1629.     else if (us.nRel == rcBiorhythm)
  1630.       gi.nMode = gBiorhythm;
  1631.     else
  1632.       gi.nMode = gWheel;
  1633.   }
  1634.   if (gi.nMode == gGrid) {
  1635.     if (us.nRel <= rcDual && us.fMidpoint && !us.fAspList)
  1636.       us.fGridConfig = fTrue;
  1637.     gs.xWin = gs.yWin =
  1638.       (gs.nGridCell + (us.nRel <= rcDual))*CELLSIZE*gi.nScale + 1;
  1639.   } else if (fMap) {
  1640.     gs.xWin = nDegMax*gi.nScale;
  1641.     gs.yWin = nDegHalf*gi.nScale;
  1642.   }
  1643. #ifdef WIN
  1644.   if (fSidebar)
  1645.     gs.xWin -= SIDESIZE;
  1646. #endif
  1647.   gi.nScaleT = gs.fPS ? PSMUL : (gs.fMeta ? METAMUL : 1);
  1648.  
  1649.   if (gi.fFile) {
  1650.     if (gs.xWin == 0)
  1651.       gs.xWin = DEFAULTX;
  1652.     if (gs.yWin == 0)
  1653.       gs.yWin = DEFAULTY;
  1654.     if (fSidebar)
  1655.       gs.xWin += SIDESIZE;
  1656.     if (gs.xWin > BITMAPX)
  1657.       gs.xWin = BITMAPX;
  1658.     if (gs.yWin > BITMAPY)
  1659.       gs.yWin = BITMAPY;
  1660.     BeginFileX();
  1661.     if (gs.fBitmap) {
  1662.       gi.cbBmpRow = (gs.xWin + 1) >> 1;
  1663.       gi.yBand = gs.yWin;
  1664.       if (!FEnsureGrid())
  1665.         return fFalse;
  1666.       while ((gi.bm = PAllocate((long)gi.cbBmpRow * gi.yBand, fTrue, NULL)) ==
  1667.         NULL) {
  1668.         PrintWarning("The bitmap must be generated in multiple stages.");
  1669.         gi.yBand = (gi.yBand + 1) / 2;
  1670.         if (gi.yBand < 1 || gs.chBmpMode != 'B')
  1671.           return fFalse;
  1672.       }
  1673.       if (gi.yBand == gs.yWin)
  1674.         gi.yBand = 0;
  1675.       else {
  1676.         gi.yOffset = gs.yWin - gs.yWin % gi.yBand;
  1677.         if (gi.yOffset == gs.yWin)
  1678.           gi.yOffset -= gi.yBand;
  1679.       }
  1680.     }
  1681. #ifdef PS
  1682.     else if (gs.fPS)
  1683.       PsBegin();
  1684. #endif
  1685. #ifdef META
  1686.     else {
  1687.       if (!FEnsureGrid())
  1688.         return fFalse;
  1689.       for (gi.cbMeta = MAXMETA; gi.cbMeta > 0 &&
  1690.         (gi.bm = PAllocate(gi.cbMeta, fTrue, NULL)) == NULL;
  1691.         gi.cbMeta -= MAXMETA/8)
  1692.         PrintWarning("Attempting to get maximum memory for metafile.");
  1693.       if (gi.cbMeta == 0)
  1694.         return fFalse;
  1695.       gs.xWin   *= METAMUL;  /* Increase chart sizes and scales behind the */
  1696.       gs.yWin   *= METAMUL;  /* scenes to make graphics look smoother.     */
  1697.       gs.nScale *= METAMUL;
  1698.     }
  1699. #endif
  1700.     InitColorsX();
  1701.   }
  1702. #ifdef ISG
  1703.   else {
  1704. #ifdef PCG
  1705.     BeginX();
  1706.     if (gs.xWin == 0 || gs.yWin == 0) {
  1707.       if (gs.xWin == 0)
  1708.         gs.xWin = xPcScreen;
  1709.       if (gs.yWin == 0)
  1710.         gs.yWin = yPcScreen;
  1711.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  1712.     } else if (fSidebar)
  1713.       gs.xWin += SIDESIZE;
  1714. #else
  1715.     if (gs.xWin == 0 || gs.yWin == 0) {
  1716.       if (gs.xWin == 0)
  1717.         gs.xWin = DEFAULTX;
  1718.       if (gs.yWin == 0)
  1719.         gs.yWin = DEFAULTY;
  1720.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  1721.     } else if (fSidebar)
  1722.       gs.xWin += SIDESIZE;
  1723.     BeginX();
  1724. #endif
  1725.   }
  1726. #endif /* ISG */
  1727.  
  1728.   if (gi.fFile || gs.fRoot)    /* Go draw the graphic chart. */
  1729.     DrawChartX();
  1730.   if (gi.fFile) {    /* Write bitmap to file if in that mode. */
  1731.     EndFileX();
  1732.     while (gi.yBand) {
  1733.       gi.yOffset -= gi.yBand;
  1734.       DrawChartX();
  1735.       EndFileX();
  1736.     }
  1737.     if (!gs.fPS)
  1738.       DeallocateHuge(gi.bm);
  1739.   }
  1740. #ifdef ISG
  1741.   else {
  1742. #ifdef X11
  1743.     if (gs.fRoot) {                                         /* Process -XB. */
  1744.       XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  1745.       XClearWindow(gi.disp, gi.root);
  1746.  
  1747.       /* If -Xn in effect with -XB, then enter infinite loop where we */
  1748.       /* calculate and animate chart, displaying on the root window.  */
  1749.       while (gs.nAnim) {
  1750.         Animate(gs.nAnim, 1);
  1751.         if (!gs.fJetTrail)
  1752.           XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  1753.         DrawChartX();
  1754.         XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  1755.         XClearWindow(gi.disp, gi.root);
  1756.       }
  1757.     } else
  1758. #endif
  1759. #ifndef WIN
  1760.       InteractX();    /* Window's up; process commands given to window now. */
  1761.     EndX();
  1762. #else
  1763.     DrawChartX();
  1764. #endif
  1765.   }
  1766. #endif /* ISG */
  1767.   return fTrue;
  1768. }
  1769. #endif /* GRAPH */
  1770.  
  1771. /* xscreen.c */
  1772.